import { ref, reactive, computed, toRaw, isReactive, isRef, type Ref } from "vue";
import { getProperty,isObj } from "@/common/utils";
import { REQUEST_SUCCESS_CODE,DEFAULT_RESPONSE_KEY,DEFAULT_TOTAL_KEY } from '@/env'
import type {PickPromise,PickFrom,KeysOf} from '@/typings/utils'

type PageLoad = (data: {
	leftList: any[],
	rightList: any[],
	addList: any[],
	pageNo?: number,
	limit?: number
}) => { pageNo: number }
const pageLoad: PageLoad = ({
	leftList,
	rightList,
	addList,
	pageNo = 1,
	limit = 20
}) => {
	// 加载内容是否为空
	if (addList.length != 0) {
		let loadListLength = leftList.length+rightList.length
		// 判断是否为第一次加载 or 第一页加载未满
		if (loadListLength == 0 || loadListLength < limit) {
			
			// 判断数据是否有变动
			if (loadListLength != addList.length) {
				leftList.splice(0, leftList.length)
				rightList.splice(0, rightList.length)
			}
		}
		addList.forEach((item,index) => {
			if(index%2 === 0){
				leftList.push(item)
			}else{
				rightList.push(item)
			}
		})
		// 加载数据是否够一页
		if (addList.length == limit) {
			pageNo++;
		}
	}
	return { pageNo };
}

interface PromiseData extends Record<any, any> {
    [key: string]: any;
};

interface Option<T extends PromiseData>  {
    responseKey?: string;//列表字段
    responseInterception?: (res: PickFrom<T, KeysOf<T>>) => void;
    params?: Record<string, any> | Ref<Record<string, any>>
    totalKey?: string,//数据总数字段
};


export const useWaterfallsPage = <A extends (data: any) => Promise<PromiseData>, T extends PickPromise<ReturnType<A>>, R extends T['rows'],D extends T['data'],DR extends T['data']['rows']>({
	api,
	option,
	pageSize = 20,
}:{ api: A, option?: Option<T>, pageSize?: number }) => {
	//定义分页所需参数，
	const showLoad = ref(false);
	type ListItem = R extends (infer I)[] ? I : D extends (infer I)[] ? I : DR extends (infer I)[] ? I : never
	const leftList = reactive<ListItem[]>([]);
	const rightList = reactive<ListItem[]>([]);
	const requestQueue: Array<Record<string, any>|undefined> = [];
	let isRefresh = false
	let page = 1;
	const isGet = ref(true)
	const allRequest = async () => {
		let arr = [...requestQueue];
		for (let index in arr) {
			await handleQueryPage(arr[index]);
			requestQueue.splice(Number(index), 1);
		}
	};
	const handleQueryPage = async (params?: Record<string, any>) => {
		if (showLoad.value) {
			// 缓存请求队列，防止上个请求未执行完，导致page不正确
			requestQueue.push(params);
			return;
		}
		if (isGet.value) {
			showLoad.value = true;
			let data = {
				pageNum: page,
				pageSize,
			};
			if (option?.params) {
				if (isRef(option.params)&&isObj(option.params.value)) {
					data = {
						...data,
						...option.params.value
					};
				} else {
					data = {
						...data,
						...option.params
					};
				}
			}
			if (params) {
				if (isReactive(params)) {
					data = { ...data, ...toRaw(params) };
				} else {
					data = { ...data, ...params };
				}
			}
			try {
				const res = await api(data)

				option?.responseInterception?.(res as PickFrom<T, KeysOf<T>>);
				showLoad.value = false;
				if (REQUEST_SUCCESS_CODE.includes(res.code)) {
					if (isRefresh) {
						// 把重置列表的操作放到请求中，可以防止重置列表时，在接口请求完成前，页面出现短暂的无数据现象
						leftList.splice(0);
						rightList.splice(0);
						isRefresh = false
					}
					let { pageNo } = pageLoad(
						{
							leftList,
							rightList,
							addList: getProperty(res, option?.responseKey || DEFAULT_RESPONSE_KEY) as any[],
							pageNo: page,
							limit:pageSize
						}
					);
					page = pageNo;

					if (leftList.length+rightList.length == getProperty(res, option?.totalKey || DEFAULT_TOTAL_KEY) as number) {
						isGet.value = false;
					}
				}

			} catch (e) {
				showLoad.value = false;
				await allRequest();
			}
		}
	};
	const handleRefresh = async (params?: Record<string, any>) => {
		isGet.value = true;
		page = 1;
		isRefresh = true;
		showLoad.value = false;
		requestQueue.splice(0, requestQueue.length);
		await handleQueryPage(params);
	};
	// 无感刷新
	const handleUpdate = async (params?: Record<string, any>) => {
		if(page > 1){
			// 当前分页数超过一页，则刷新数据
			const oldPage = page
			const oldPageSize = pageSize
			const oldIsGet = isGet.value
			page = 1
			pageSize = leftList.length+rightList.length
			isGet.value = true
			isRefresh = true;
			showLoad.value = false;
			requestQueue.splice(0, requestQueue.length);
			await handleQueryPage(params);
			page = oldPage
			pageSize = oldPageSize
			isGet.value = oldIsGet;
		}else{
			// 空数据或未请求数据的情况下，调用handleRefresh
			await handleRefresh(params)
		}
	};
	const isEmpty = computed(() => leftList.length+rightList.length === 0)
	return {
		showLoad,
		isGet,
		leftList,
		rightList,
		isEmpty,
		handleQueryPage,
		handleRefresh,
		handleUpdate
	};
}
